﻿using System.Collections.Generic;
using System.Linq;
using mqtttLib.Helper;
using mqtttLib.Messages.Base;

namespace mqtttLib.Messages
{
    /// <summary>
    /// 发布消息
    /// </summary>
    public sealed class PublishMessage : MqttMessagePacketId
    {
        /// <summary>
        /// 主题
        /// </summary>
        public string TopicName { get; set; }
        /// <summary>
        /// 内容
        /// </summary>
        public byte[] Payload { get; set; }

        public PublishMessage()
            : base(MessageType.PUBLISH)
        {
        }



        public override byte[] GetDataBytes()
        {
            var result = new LinkedList<byte>();
            //variable header
            if (FixedHeader.Qos == Qos.AtLeastOnce || FixedHeader.Qos == Qos.ExactlyOnce)
            {
                if (!FixedHeader.Dup)
                    PacketIdentifier = GetPacketIdentifier();
                result.AddLast(PacketIdentifier);
            }
            result.AddLast(TopicName);
            result.AddLast(Payload);        //有效载荷 
            FixedHeader.RemaingLength = result.Count;
            result.AddFirst(FixedHeader.GetDataBytes());
            return result.ToArray();


        }


        public override void GetDataObject(byte[] buffers)
        {
            int offset = GetStartOffset(buffers);  // int offset = buffers.Length - FixedHeader.RemaingLength;


            if (FixedHeader.Qos == Qos.AtLeastOnce || FixedHeader.Qos == Qos.ExactlyOnce)
                PacketIdentifier = buffers.ReadShort(ref offset);
            if (buffers.Length > 2)
            {
                TopicName = buffers.ReadString(ref offset);
                Payload = buffers.Read(ref offset, buffers.Length - offset);

            }
        }
    }


    /// <summary>
    /// QoS  1 发布回复 
    /// </summary>
    public sealed class PublishAckMessage : MqttMessagePacketId
    {

        public PublishAckMessage()
            : base(MessageType.PUBACK)
        {
        }


        public override byte[] GetDataBytes()
        {
            var result = new LinkedList<byte>();
            //variable header
            if (FixedHeader.Qos == Qos.AtLeastOnce || FixedHeader.Qos == Qos.ExactlyOnce)
            {
                // PacketIdentifier = GetPacketIdentifier();
                result.AddLast(PacketIdentifier);
            }
            FixedHeader.RemaingLength = result.Count;
            result.AddFirst(FixedHeader.GetDataBytes());
            return result.ToArray();
        }


        public override void GetDataObject(byte[] buffers)
        {
            int offset = GetStartOffset(buffers);  // int offset = buffers.Length - FixedHeader.RemaingLength;

            if (FixedHeader.Qos == Qos.AtLeastOnce || FixedHeader.Qos == Qos.ExactlyOnce)
                PacketIdentifier = buffers.ReadShort(ref offset);
        }

    }

    /// <summary>
    /// QoS 2 发布消息 返回 步骤 1
    /// </summary>
    public sealed class PublishRecMessage : MqttMessagePacketId
    {
        public PublishRecMessage()
            : base(MessageType.PUBREC)
        {
        }


        public override byte[] GetDataBytes()
        {
            var result = new LinkedList<byte>();
            //variable header
            if (FixedHeader.Qos == Qos.AtLeastOnce || FixedHeader.Qos == Qos.ExactlyOnce)
            {
                PacketIdentifier = GetPacketIdentifier();
                result.AddLast(PacketIdentifier);
            }
            FixedHeader.RemaingLength = result.Count;
            result.AddFirst(FixedHeader.GetDataBytes());
            return result.ToArray();
        }


        public override void GetDataObject(byte[] buffers)
        {
            int offset = GetStartOffset(buffers);  // int offset = buffers.Length - FixedHeader.RemaingLength;
            PacketIdentifier = buffers.ReadShort(ref offset);
        }

    }

    /// <summary>
    /// 发布消息 取消
    /// QoS 2 发布消息 返回 步骤 2
    /// </summary>
    public sealed class PublishRelMessage : MqttMessagePacketId
    {
        public PublishRelMessage()
            : base(MessageType.PUBREL)
        {
        }


        public override byte[] GetDataBytes()
        {
            var result = new LinkedList<byte>();
            //variable header
            if (FixedHeader.Qos == Qos.AtLeastOnce || FixedHeader.Qos == Qos.ExactlyOnce)
            {
                PacketIdentifier = GetPacketIdentifier();
                result.AddLast(PacketIdentifier);
            }

            FixedHeader.RemaingLength = result.Count;
            result.AddFirst(FixedHeader.GetDataBytes());
            return result.ToArray();
        }
        public override void GetDataObject(byte[] buffers)
        {
            int offset = GetStartOffset(buffers);  // int offset = buffers.Length - FixedHeader.RemaingLength;
            //variable header
            if (FixedHeader.Qos == Qos.AtLeastOnce || FixedHeader.Qos == Qos.ExactlyOnce)
                PacketIdentifier = buffers.ReadShort(ref offset);
        }
    }

    /// <summary>
    /// 
    ///  QoS 2 发布消息 成功 返回 步骤 3
    /// </summary>
    public sealed class PublishCompMessage : MqttMessagePacketId
    {
        public PublishCompMessage()
            : base(MessageType.PUBCOMP)
        {
        }

        public override byte[] GetDataBytes()
        {
            var result = new LinkedList<byte>();
            //variable header
            if (FixedHeader.Qos == Qos.AtLeastOnce || FixedHeader.Qos == Qos.ExactlyOnce)
            {
                PacketIdentifier = GetPacketIdentifier();
                result.AddLast(PacketIdentifier);
            }
            FixedHeader.RemaingLength = result.Count;
            result.AddFirst(FixedHeader.GetDataBytes());
            return result.ToArray();
        }


        public override void GetDataObject(byte[] buffers)
        {
            int offset = GetStartOffset(buffers);  // int offset = buffers.Length - FixedHeader.RemaingLength;
            //variable header
            if (FixedHeader.Qos == Qos.AtLeastOnce || FixedHeader.Qos == Qos.ExactlyOnce)
                PacketIdentifier = buffers.ReadShort(ref offset);
        }

    }
}